package org.marverse.scripting

import util.{MutableTypedMap, Util, Checkable}
import java.util.IdentityHashMap
import ScriptingUtil._

trait UncheckedExpression {
  def childUncheckedExpressions: Seq[_ <: UncheckedExpression]
  def checked(implicit ctx: MutableTypedMap[TypedKey, Any]): Expression
}

trait Expression extends Checkable {

  def check(implicit ctx: MutableTypedMap[TypedKey, Any]) {
    // NOTE: this check for recursiveness is not thread-safe
    // would be thread-safe if Expression.seen were thread-local 
    def doCheck {
      assertThat(!(Expression.seen containsKey this), "Expression: recursive")
      Expression.seen put(this, ())
      Util.checkChildren(this, ctx)
    }
    
    if (Expression.seen == null) {
      Expression.seen = new IdentityHashMap()
      doCheck
      Expression.seen = null
    }
    else
      doCheck
  }
  
  def childExpressions: Seq[_ <: Expression]
  def expressionType(implicit ctx: MutableTypedMap[TypedKey, Any]): Type
  def evaluate(implicit ctx: MutableTypedMap[TypedKey, Any]): Any
}

object Expression {
  private var seen: IdentityHashMap[Expression, unit] = null
}